﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace pong1
{
    /// <summary>
    /// One argument of an event, it has a name, value and type
    /// </summary>
    public struct EventArgument
    {
        private String argumentName;
        private String argumentValue;
        private String argumentType;

        public String ArgumentName
        {
            get { return argumentName; }
            set { argumentName = value; }
        }
        
        public String ArgumentValue
        {
            get { return argumentValue; }
            set { argumentValue = value; }
        }

        
        public String ArgumentType
        {
            get { return argumentType; }
            set { argumentType = value; }
        }
    }

    /// <summary>
    /// An event. It has a name, a set of arguments, and a delivery time
    /// </summary>
    public class Event
    {
        private String eventName;                   // The unique event name
        private EventArgument[] eventArguments;    // An array of event arguments
        private int deliveryTime;                   // This can be used to post events into the future
        private const int number_of_arguments = 8;

        public int DeliveryTime
        {
            get { return deliveryTime; }
            set { deliveryTime = value; }
        }

        public String EventName
        {
            get { return eventName; }
            set { eventName = value; }
        }

        public EventArgument[] EventArguments
        {
            get { return eventArguments; }
            set { eventArguments = value; }
        }

        public Event()
        {
            eventArguments = new EventArgument[number_of_arguments];
            deliveryTime = 0;
        }

    }


    /// <summary>
    /// A struct storing the EventName and its EventReceiver
    /// </summary>
    public struct EventNameAndReceiver
    {
        String eventName;
        String eventReceiver;

        public String EventName
        {
            get { return eventName; }
            set
            {
                eventName = value;
            }
        }

        public String EventReceiver
        {
            get { return eventReceiver; }
            set
            {
                eventReceiver = value.ToLower();
            }
        }
    }

    /// <summary>
    /// This class contains a list of pending events (== commands).
    /// It also stores a List of all Event-Names & their Event-Receivers
    /// Event-Receivers can use this list to check whether an event concerns 
    /// them and check for that event on the event collection.
    /// It also stores a list of Event-Names and their set of arguments -> this variable is not being used now.
    /// These two lists could be used to add new events without having to recompile all the code
    /// </summary>
    public class EventCollection
    {
        List <Event> eventList;     // Stores list of events to be executed

        List <EventNameAndReceiver> eventNameAndReceivers;

        public EventCollection()
        {
            eventList = new List<Event>();
            eventNameAndReceivers = new List<EventNameAndReceiver>();
            loadEventNameAndReceivers();
        }
        
        /// <summary>
        /// Load events into list of event names and their receivers. This can be hardcoded or read from a file
        /// Currently not used.
        /// 
        /// file format could be: 
        /// line 1 [number_of_events]
        /// line 2 [eventname1 eventReceiver]
        /// line 3 [eventArgName1 eventArg1Type eventArgName2 eventArg2Type eventArgName3 eventArg3Type ...]
        /// line 4 [eventname2 eventReceiver]
        /// line 5 [eventArgName1 eventArg1Type eventArgName2 eventArg2Type eventArgName3 eventArg3Type ...]
        /// </summary>
        private void loadEventNameAndReceivers()
        {
            //EventNameAndReceiver enar = new EventNameAndReceiver();
            //enar.EventName = "ballmoves";        
            //enar.EventReceiver = "physics";
            //eventNameAndReceivers.Add(enar);
        }

        /// <summary>
        /// Allows any object to register itself as a listener for a certain event
        /// The object sends the event name and its own name
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="eventReceiver"></param>
        public void RegisterForEvent(String eventName, String eventReceiver)
        {
            EventNameAndReceiver enar = new EventNameAndReceiver();
            enar.EventName = eventName.ToLower().Trim();
            enar.EventReceiver = eventReceiver.ToLower().Trim();
            eventNameAndReceivers.Add(enar);
        }

        /// <summary>
        /// This function returns a comma separated list of events that the receiver listens for.
        /// </summary>
        /// <param name="eventReceiver"></param>
        /// <returns></returns>
        public String GetEventsForReceiver(String eventReceiver)
        {
            if (eventNameAndReceivers.Count == 0)
                return "";

            eventReceiver = eventReceiver.ToLower();
            String eventsList = "";
            foreach (EventNameAndReceiver item in eventNameAndReceivers)
        	{
                if (item.EventReceiver == eventReceiver)
                {
                    eventsList = eventsList + item.EventName + ",";
                }
	        }
            return eventsList;
        }
        /// <summary>
        /// Adds an event to the event list
        /// </summary>
        public void Add(Event e)
        {
            eventList.Add(e);
        }

        /// <summary>
        /// Removes an event from the event list
        /// </summary>
        public void Remove(Event e)
        {
            eventList.Remove(e);
        }

        /// <summary>
        /// Returns a reference to an event on the eventList, doesn't remove it
        /// </summary>
        public Event SearchEvent(String eventName)
        {
            foreach (var eventInList in eventList)
	        {
                if (eventInList.EventName == eventName /*&& eventInList.deliveryTime <= currentTime*/ )
                {
                    return eventInList;
                }
            }
            return null;
            
        }

        /// <summary>
        /// Returns an event on the eventList, and removes it
        /// BUG WARNING - this only returns the first event with name 'eventName', what if there are multiple such events?
        /// </summary>
        public Event RetrieveEvent(String eventName)
        {
            Event ecopy = new Event();
            foreach (var eventInList in eventList)
            {
                if (eventInList.EventName == eventName /*&& eventInList.deliveryTime <= currentTime*/ )
                {
                    ecopy = eventInList;
                    eventList.Remove(eventInList);
                    return ecopy;
                }
            }
            return null;

        }

        public bool IsEmpty() 
        {
            if (eventList.Count == 0)
                return true;
            else
                return false;
        }


    }


}
